//      algo_test.cc
//      
//      Copyright 2012 tqlong <tqlong@espada>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.

#include <iostream>
#include <boost/program_options.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

//#include "../algo.h"
#include "stl-helper.h"
#include "data.h"
#include "../kmean.h"

namespace po = boost::program_options;
po::options_description desc("Allowed options");
po::variables_map vm;

void process_options(int argc, char** argv);
void usage(int exitcode = 0);

void test_read();
void test_kmean();
void test_sparse();

int main(int argc, char** argv)
{
  std::cerr << "hmm tests ..." << std::endl;
  srand((unsigned int)time(NULL));

  process_options(argc, argv);

  boost::posix_time::ptime time_start(boost::posix_time::microsec_clock::local_time());

  if (vm.count("help"))
    usage();
  else if (vm.count("read"))
    test_read();
  else if (vm.count("kmean"))
    test_kmean();
  else if (vm.count("sparse"))
    test_sparse();
  else 
    usage();

  boost::posix_time::ptime time_end(boost::posix_time::microsec_clock::local_time());
  boost::posix_time::time_duration duration(time_end - time_start);
  std::cerr << "Duration = " << duration << "\n";
}

void test_read() 
{
  std::string inputFile = vm["input"].as<std::string>();
  std::string outputFile = vm["output"].as<std::string>();

  GeneralData<SimplestReader> d(inputFile);
  DataSubset<GeneralData<SimplestReader> > d_sub(d);
  d_sub.randperm();
  DataReader::save(outputFile, d_sub);
  
  std::vector<std::string> fname;
  fname.pb("m1");
  fname.pb("m2");
  GeneralData<SimplestMultiFileReader> d1(fname);
  DataSubset<GeneralData<SimplestMultiFileReader> > d1_sub(d1);
  d1_sub.randperm();
  DataReader::save(outputFile+".mf", d1_sub);
}

void test_kmean()
{
  std::string inputFile = vm["input"].as<std::string>();
  std::string outputFile = vm["output"].as<std::string>();
  
  GeneralData<SimplestReader> d(inputFile);
  
  KMean<typeof(d)> kmean(vm, d);
  kmean.run();  
  kmean.save(outputFile); 
}

void test_sparse()
{
  std::string inputFile = vm["input"].as<std::string>();
  std::string outputFile = vm["output"].as<std::string>();
  
  GeneralData<SimplestSparseReader> d(inputFile);
  DataReader::save(outputFile, d);
  
  KMean<typeof(d)> kmean(vm, d);
  kmean.run();  
  kmean.save(outputFile); 
}

void usage(int exitcode)
{
  std::cout << desc << std::endl;
  exit(exitcode);
}

void process_options(int argc, char** argv)
{
  desc.add_options()
    ("help", "produce this usage")
    ("input", po::value<std::string>(), "input file")
    ("output", po::value<std::string>(), "output file (final result)")
    ("debug", po::value<std::string>()->default_value("debug"), "debug file (iteration result)")

    ("read", "test the MatrixData class\n   --input --output")
    ("kmean", "test the KMean class\n   --input --K --iter --output")    
    ("sparse", "test the sparse Kmean\n   --input --K --iter --output")    

    ("labelidx", po::value<int>()->default_value(-1), "label column index")
    ("iter", po::value<int>()->default_value(100), "maximum number of iterations")
    ("K", po::value<int>()->default_value(2), "number of cluster centers")
    ;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);
}

